<html>
<head><meta charset="utf-8"><title>Lifetime question · t-compiler/wg-nll · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/index.html">t-compiler/wg-nll</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html">Lifetime question</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="209061869"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209061869" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209061869">(Sep 04 2020 at 07:13)</a>:</h4>
<p>I got this program:</p>
<div class="codehilite"><pre><span></span><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">123</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">l2</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>It currently compiles fine on current stable. However i feel that the two borrow region should not overlap...  In my naive understanding i thought this should be a compile error...  Did i miss something?</p>



<a name="209062188"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209062188" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209062188">(Sep 04 2020 at 07:17)</a>:</h4>
<p><code>l2</code> there is being coerced to a <code>&amp;i32</code>, so it is never actually used like a unique reference</p>



<a name="209062337"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209062337" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209062337">(Sep 04 2020 at 07:19)</a>:</h4>
<p>I think you can argue this is correct using two-stage borrows (where the second stage never happens, so it is effectively just as if you had declared two shared references and compared them)</p>



<a name="209062719"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209062719" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209062719">(Sep 04 2020 at 07:24)</a>:</h4>
<p>Thanks, but i thought two-stage borrows is still in proposal stage instead of reaching stable release?</p>



<a name="209063007"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209063007" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209063007">(Sep 04 2020 at 07:28)</a>:</h4>
<p>Also, i tried to "activate" those references:</p>
<div class="codehilite"><pre><span></span><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">123</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">l1</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="o">*</span><span class="n">l2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">234</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">l2</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">l1</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>This compiles too.</p>



<a name="209063272"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209063272" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> NeoRaider <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209063272">(Sep 04 2020 at 07:32)</a>:</h4>
<p>The first borrow ends with the last use of l1, which is the println in line 4. It is not borrowed anymore when you borrow it for l2.</p>



<a name="209064310"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064310" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064310">(Sep 04 2020 at 07:46)</a>:</h4>
<p>yes, i can understand that. but if i name the immutable borrow lifetime <code>'a</code> and unique borrow lifetime <code>'b</code>, they should not overlap, and l1's type is <code>&amp;'a i32</code> and it's incompatible with <code>&amp;'b mut i32</code> or <code>&amp;'b i32</code>, isn't it?</p>



<a name="209064367"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064367" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064367">(Sep 04 2020 at 07:47)</a>:</h4>
<p><code>'a</code> ends after the first <code>println</code> and starts again on the second assignment</p>



<a name="209064459"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064459" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064459">(Sep 04 2020 at 07:48)</a>:</h4>
<p>yes, i imagine this is fine. but doesn't <code>'a</code> and <code>'b</code> have to exclude each other?</p>



<a name="209064502"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064502" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064502">(Sep 04 2020 at 07:49)</a>:</h4>
<p>(maybe not in two-stage borrows i think.)</p>



<a name="209064741"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064741" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064741">(Sep 04 2020 at 07:52)</a>:</h4>
<p>The borrows can't overlap. The immutable borrow is only for the first part of <code>'a</code>.</p>



<a name="209064871"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209064871" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209064871">(Sep 04 2020 at 07:53)</a>:</h4>
<p>i can understand why this is fine:</p>
<div class="codehilite"><pre><span></span><code><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">123</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">l1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">i</span><span class="p">;</span><span class="w"></span>
</code></pre></div>


<p>just not sure about the validity of the assignment <code>l1 = l2</code>, i thought their lifetimes are mutual exclusive.</p>



<a name="209071041"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071041" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071041">(Sep 04 2020 at 09:15)</a>:</h4>
<p>This code is certainly dynamically okay, in the sense that it doesn't actually execute undefined behavior, and the analyses have become more complex to try to statically determine that it is okay. I missed the fact that <code>l1</code> is dead after its definition because it is not reused. I know that polonius will explicitly allow the new <code>l1</code> value to have a different lifetime than the first one, and stacked borrows will definitely allow this because it doesn't actually use the values in any interesting way, but I'm not exactly sure how the NLL analysis proves this one.</p>



<a name="209071256"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071256" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071256">(Sep 04 2020 at 09:17)</a>:</h4>
<p><span class="user-mention" data-user-id="116118">@Matthew Jasper</span> Are you saying that <code>'a</code> is not an interval in time?</p>



<a name="209071415"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071415" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071415">(Sep 04 2020 at 09:18)</a>:</h4>
<p><code>'a</code> is a set of points in the CFG, it can have gaps.</p>



<a name="209071417"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071417" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071417">(Sep 04 2020 at 09:18)</a>:</h4>
<p>I didn't think NLL allows lifetimes that are not contiguous (in dynamic execution time)</p>



<a name="209071468"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071468" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071468">(Sep 04 2020 at 09:19)</a>:</h4>
<p>Like variable live regions, it should be an interval-closed subset of the CFG</p>



<a name="209071624"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209071624" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209071624">(Sep 04 2020 at 09:21)</a>:</h4>
<p>If you just let borrow regions drop out you can get easy bad behavior, e.g.</p>
<div class="codehilite"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">vec</span><span class="o">!</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="na">&#39;a</span><span class="w"> </span><span class="n">v</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span><span class="w"></span>
<span class="p">(</span><span class="o">&amp;</span><span class="na">&#39;b</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">v</span><span class="p">).</span><span class="n">push</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span><span class="w"></span>
<span class="k">use</span><span class="p">(</span><span class="n">x</span><span class="p">);</span><span class="w"></span>
</code></pre></div>


<p>We could say that <code>'a</code> covers lines 2 and 4 and <code>'b</code> covers line 3 and then they are disjoint</p>



<a name="209080240"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122657-t-compiler/wg-nll/topic/Lifetime%20question/near/209080240" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lqd <a href="https://rust-lang.github.io/zulip_archive/stream/122657-t-compiler/wg-nll/topic/Lifetime.20question.html#209080240">(Sep 04 2020 at 11:05)</a>:</h4>
<p>btw if you dump the NLL MIR you'll have at the top of the file the inferred values of the cfg points per region; <code> -Zdump-mir=nll</code> -&gt; <code>./mir_dump/$function.mir</code> like</p>
<div class="codehilite"><pre><span></span><code>| Inferred Region Values
| &#39;_#0r | U0 | {bb0[0..=34], bb1[0], bb2[0..=9], bb3[0..=2], bb4[0..=44], bb5[0..=9], bb6[0..=2], bb7[0..=12], &#39;_#0r, &#39;_#1r}
| &#39;_#1r | U0 | {bb0[0..=34], bb1[0], bb2[0..=9], bb3[0..=2], bb4[0..=44], bb5[0..=9], bb6[0..=2], bb7[0..=12], &#39;_#1r}
| &#39;_#2r | U0 | {bb0[12], bb4[22]}
</code></pre></div>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>